package playn.client;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

import tiled.simple.core.Map;


import playn.html.HtmlAssets;
import playn.html.HtmlGame;
import playn.html.HtmlPlatform;
import playn.platformer.Controls;
import playn.platformer.Game;
import playn.client.GameService;
import playn.client.GameServiceAsync;
import playn.core.Image;
import playn.core.PlayN;
import playn.core.ResourceCallback;

import static playn.core.PlayN.assets;
import static playn.core.PlayN.graphics;

public class Loader extends HtmlGame{
    
    Game game=null;

	private HashMap<String,Image> imagesCache = new HashMap<String, Image>(){
		private static final long serialVersionUID = 1L;
		{
			put("TileSetVX___Global_4.png",null);
			put("sonic_left.png"		  ,null);
			put("sonic_right.png"		  ,null);
			put("mask.png"		          ,null);
		}
	};
	
    
    private final GameServiceAsync gameService = (GameServiceAsync) GWT.create(GameService.class);

    
    public static int RESOURCES_TO_ASYNC_LOAD=0;
    
    
	@Override
	public void start() {
		
    	HtmlAssets assets = HtmlPlatform.register().assets();
    	assets.setPathPrefix("/");

    	isAllImagesLoaded();
    	
		Iterator<Entry<String, Image>> itr = imagesCache.entrySet().iterator();
	    while (itr.hasNext()) {
	    	Entry <String,Image> element = itr.next();
	    	String source=element.getKey();
    		asyncLoadImage(source);
	    	
	    }
	    	
		Log.info("async call of getMapData");
    	gameService.getGameData(new AsynchronousCallback());
	}
	
	private void asyncLoadImage(String source){
		Log.info("async load of "+source+" image");
		Image image=assets().getImage(source);
	    image.addCallback(new AsynchronousCallback(source));
	    
	}
	
	private class AsynchronousCallback implements ResourceCallback<Image>,AsyncCallback<HashMap<String,Map>>{
		private String source;

		public AsynchronousCallback(){
		}
		
		public AsynchronousCallback(String source){
			this.source=source;
		}

		public void done(Image image) {
			imagesCache.put(source,image);
			Log.info("loaded "+ source + " ready="+image.isReady()+" isAllImagesLoaded="+isAllImagesLoaded());
        	CheckAllAndFinalyStartTheGame();
		}

		public void error(Throwable err) {
			Log.error(err.getMessage());
		}

		public void onFailure(Throwable err) {
			Log.error(err.getMessage());
		}

		public void onSuccess(HashMap<String, Map> maps) {
        	Controls controls = new Controls();
        	game = new Game(maps,controls,imagesCache);

        	Iterator<Entry<String, Map>> itr=maps.entrySet().iterator();
        	
        	while(itr.hasNext()){
        		Log.info("loaded "+itr.next().getKey());
        	}

        	CheckAllAndFinalyStartTheGame();
		}
	}
	
	public boolean isAllImagesLoaded(){
		boolean flag=true;
		Iterator<Entry<String, Image>> itr = imagesCache.entrySet().iterator();
	    while (itr.hasNext()) {
	    	Entry <String,Image> element = itr.next();
	    	
	    	if( element.getValue()==null){
	    		flag=false;
		    	Log.info("checking "+element.getKey()+" null");
	    	} else if (!element.getValue().isReady()) {
	    		flag=false;
		    	Log.info("checking "+element.getKey()+" not ready yet");
	    	} else {
		    	Log.info("checking "+element.getKey()+" flag="+flag);

	    	}
	    	
	    }
		return flag;
	}
	
	
	private void CheckAllAndFinalyStartTheGame(){
		if((isAllImagesLoaded()==true)&&(game!=null)){

			Log.info("starting the game");

			Window.addResizeHandler(new ResizeHandler() {
                public void onResize(ResizeEvent event){
                	graphics().setSize(event.getWidth(), event.getHeight());
                }
            });

            PlayN.run(game);
		}
	}


}
